package cn.wolfcode.crm.shiro;

import cn.wolfcode.crm.domain.Customer;
import cn.wolfcode.crm.domain.Employee;
import cn.wolfcode.crm.mapper.CustomerMapper;
import cn.wolfcode.crm.mapper.EmployeeMapper;
import cn.wolfcode.crm.mapper.PermissionMapper;
import cn.wolfcode.crm.mapper.RoleMapper;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.credential.CredentialsMatcher;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.List;

//认证数据源
@Component("crmRealm")
public class CRMRealm extends AuthorizingRealm {

    @Autowired
    private EmployeeMapper employeeMapper;

    @Autowired
    private RoleMapper roleMapper;

    @Autowired
    private PermissionMapper permissionMapper;

    //@Autowired
    //private CustomerMapper customerMapper;

    //从Spring容器中找到credentialsMatcher,注入进去
    @Autowired
    public void setCredentialsMatcher(CredentialsMatcher credentialsMatcher) {
        super.setCredentialsMatcher(credentialsMatcher);
    }

    /**
     * 认证
     *
     * @param authenticationToken
     * @return
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        //获取登录的身份(令牌中的用户名)
        Object principal = authenticationToken.getPrincipal();
        //查询数据库中是否有该身份，如果有就返回相关信息
        //模拟admin;1
        // String username = "admin";
        // String password = "1";

      /*  //添加客户时的电话和QQ验证，查询数据库中电话号码和QQ是否已经存在
        Subject subject = SecurityUtils.getSubject();
        Customer customer = (Customer) subject.getPrincipal();
        customerMapper.selectByTel(customer.getTel());
        if(!customerMapper.ExistTel()){
            return new SimpleAuthenticationInfo()
        }*/

        //查询数据库中是否有该账户
        Employee employee = employeeMapper.selectByName((String) principal);

        if (employee != null) {
            //info中必须包含密码信息，提供给其他主键进行密码匹配
            //三个参数：用户名，密码，记录信息来源的数据源的名字
            //return new SimpleAuthenticationInfo(employee.getName(),employee.getPassword(),"crmRealm");
            //加密后的密码匹配，多一个参数的SimpleAuthenticationInfo方法

            //第一个参数：身份（包含了身份的信息，是对应的对象，在获取身份时才能拿到主体对象来操作）
            return new SimpleAuthenticationInfo(employee, employee.getPassword(),
                    ByteSource.Util.bytes(employee.getName()), "crmRealm");
        }

        //如果没有就返回null
        return null;
    }

    /**
     * 提供授权相关的信息:在需要判断权限的时候才会执行到该方法
     *
     * @param principalCollection
     * @return
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        System.out.println("执行了权限验证的方法！");
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        //拿到主体
        Subject subject = SecurityUtils.getSubject();
        //用主体拿到身份：员工对象
        Employee employee = (Employee) subject.getPrincipal();
        //判断是否是超级管理员
        if (employee.isAdmin()) {
            info.addRole("admin");//添加角色
            info.addStringPermission("*:*");//添加权限：可使用通配符
        } else {
            //写假数据测试
            //info.addRole("admin");//添加角色
            //info.addStringPermission("user:delete");//添加权限

            //普通用户：当前用户有哪些角色/权限，全部查询出来后添加到info对象中
            List<String> roles = roleMapper.selectSnByEmpId(employee.getId());//查角色
            //把查询出角色和权限添加进入info
            info.addRoles(roles);//添加角色
            List<String> permissions = permissionMapper.selectPermByEmpId(employee.getId());//查权限
            info.addStringPermissions(permissions);//添加权限
        }

        return info;//返回权限信息
    }
}
